package com.sky.service.impl;

import cn.hutool.core.collection.CollUtil;
import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.sky.context.BaseContext;
import com.sky.dto.OrdersPageQueryDTO;
import com.sky.dto.OrdersPaymentDTO;
import com.sky.dto.OrdersSubmitDTO;
import com.sky.entity.*;
import com.sky.exception.BaseException;
import com.sky.exception.OrderBusinessException;
import com.sky.mapper.OrderDetailMapper;
import com.sky.mapper.OrderMapper;
import com.sky.mapper.ShoppingCartMapper;
import com.sky.mapper.UserMapper;
import com.sky.result.PageResult;
import com.sky.service.AddressBookService;
import com.sky.service.OrderService;
import com.sky.service.ShoppingCartService;
import com.sky.utils.WeChatPayUtil;
import com.sky.vo.OrderPaymentVO;
import com.sky.vo.OrderSubmitVO;
import com.sky.vo.OrderVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * TODO
 *
 * @Author mr.zhang
 * Date 2025/6/3 16:34
 */
@Service
@Slf4j
public class OrderServiceImpl implements OrderService {
    @Autowired
    private AddressBookService addressBookService;
    @Autowired
    private OrderMapper orderMapper;
    @Autowired
    private ShoppingCartMapper shoppingCartMapper;
    @Autowired
    private ShoppingCartService shoppingCartService;
    @Autowired
    private OrderDetailMapper orderDetailMapper;
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private WeChatPayUtil weChatPayUtil;
    /**
     * 用户下单
     *
     * @param dto
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public OrderSubmitVO submit(OrdersSubmitDTO dto) {
        //1.对于异常情况的判断
        //1.1判断地址是否为空
        AddressBook addressBook = addressBookService.getById(dto.getAddressBookId());
        if (addressBook==null){
            throw new BaseException("地址为空,无法下单");
        }
        //1.2判断购物车是否为空
        List<ShoppingCart> shoppingCartList = shoppingCartService.showShoppingCart();
        if (CollUtil.isEmpty(shoppingCartList)){
            throw new BaseException("购物车数据为空,无法下单");
        }
        //2.封装orders数据
        Orders orders = new Orders();
        BeanUtils.copyProperties(dto,orders);
        orders.setPhone(addressBook.getPhone());
        orders.setAddress(addressBook.getDetail());
        orders.setConsignee(addressBook.getConsignee());
        orders.setStatus(Orders.PENDING_PAYMENT);//设置订单状态为待付款
        orders.setOrderTime(LocalDateTime.now());
        orders.setPayStatus(Orders.UN_PAID);//设置支付状态为未支付
        orders.setUserId(BaseContext.getCurrentId());
        //订单号自己设置
        orders.setNumber(String.valueOf(System.currentTimeMillis()));
        //3.上传数据到订单表
        orderMapper.insert(orders);
        //4.上传数据到订单明细表
        //4.1获取订单明细表的相关数据
        List<OrderDetail> orderDetailList = new ArrayList<>();
        for (ShoppingCart shoppingCart : shoppingCartList) {
            OrderDetail orderDetail = new OrderDetail();
            BeanUtils.copyProperties(shoppingCart,orderDetail);
            orderDetail.setOrderId(orders.getId());

            orderDetailList.add(orderDetail);
        }
        //4.2批量添加
        orderDetailMapper.batchInsert(orderDetailList);
        //5.封装返回数据
        OrderSubmitVO vo = new OrderSubmitVO();
        vo.setId(orders.getId());
        vo.setOrderTime(LocalDateTime.now());
        vo.setOrderNumber(orders.getNumber());
        vo.setOrderAmount(orders.getAmount());

        return vo;
    }

    /**
     * 订单支付
     *
     * @param dto
     * @return
     */
    @Override
    public OrderPaymentVO payment(OrdersPaymentDTO dto) throws Exception {
        //获取当前登录用户的id
        Long userId = BaseContext.getCurrentId();
        User user = userMapper.getById(userId);

        //调用微信支付接口,生成预支付交易单
        JSONObject jsonObject = weChatPayUtil.pay(
                dto.getOrderNumber(),//商户订单号
                new BigDecimal(0.01),//支付金额,单位 元
                "苍穹外卖订单",//商品描述
                user.getOpenid()
        );

        if (jsonObject.getString("code")!=null && jsonObject.getString("code").equals("ORDERPAID")){
            throw new OrderBusinessException("该订单已支付");
        }

        OrderPaymentVO vo = jsonObject.toJavaObject(OrderPaymentVO.class);
        //由于package是关键字,所以字段不能是package,是packageStr,所以需要手动映射
        vo.setPackageStr(jsonObject.getString("package"));

        return vo;
    }

    /**
     * 支付成功,修改订单状态
     *
     * @param outTradeNo
     */
    @Override
    public void paySuccess(String outTradeNo) {
        //获取当前登录用户的id
        Long userId = BaseContext.getCurrentId();
        //根据订单号与用户id查询订单数据
        Orders order = orderMapper.getByNumberAndUserId(outTradeNo,userId);
        //封装数据到新的Orders实例中
        Orders buildOrder = Orders.builder()
                .id(order.getId()).status(Orders.TO_BE_CONFIRMED)
                .payStatus(Orders.PAID)
                .checkoutTime(LocalDateTime.now())
                .build();
        //更新数据
        orderMapper.update(buildOrder);
    }


    /**
     * 历史订单查询
     *
     * @param
     * @return
     */
    @Override
    public PageResult historyOrders(int page, int pageSize, Integer status) {
        OrdersPageQueryDTO ordersPageQueryDTO = new OrdersPageQueryDTO();
        ordersPageQueryDTO.setUserId(BaseContext.getCurrentId());
        ordersPageQueryDTO.setStatus(status);
        //1.封装分页数据
        PageHelper.startPage(page,pageSize);
        //2.调用mapper方法获取数据
        //2.1先查询订单信息列表
        Page<Orders> ordersList = orderMapper.historyOrders(ordersPageQueryDTO);
//        判断获取的订单列表是否为空
        if (CollUtil.isEmpty(ordersList)){
            throw new BaseException("获取的订单列表为空");
        }
        //获得原始的page对象
        List<OrderVO> orderVOList = new ArrayList<>();
        //遍历查询订单详情数据,并添加
        for (Orders or : ordersList) {
            Long id = or.getId();
            List<OrderDetail> orderDetailList = orderDetailMapper.selectByOrderId(id);

            OrderVO orderVO = new OrderVO();
            //根据用户id查询订单详情信息

//            if (CollUtil.isEmpty(orderDetailList)){
//                throw new BaseException("订单明细为空");
//            }
            BeanUtils.copyProperties(or,orderVO);
            orderVO.setOrderDetailList(orderDetailList);

            orderVOList.add(orderVO);
        }
        //3.封装并返回数据
        return new PageResult(ordersList.getTotal(),orderVOList);
    }

    /**
     * 查询订单详情
     *
     * @param id
     * @return
     */
    @Override
    public OrderVO orderDetail(Long id) {
        //1.查询订单详情
        Orders order = orderMapper.getById(id);
        //判断订单是否存在
        if (order==null){
            throw new BaseException("没有订单");
        }
        //2.查询订单明细详情,根据订单id
        List<OrderDetail> orderDetailList = orderDetailMapper.getByOrderId(id);
        //3.封装并返回数据
        OrderVO orderVO = new OrderVO();
        BeanUtils.copyProperties(order,orderVO);
        orderVO.setOrderDetailList(orderDetailList);

        return orderVO;
    }


    /**
     * 取消订单
     *
     * @param id
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void cancel(Long id) {
        //1.先根据订单查询订单是否存在
        Orders orders = orderMapper.getById(id);
        if (orders==null){
            log.error("此id对应的订单不存在,无需取消");
        }
        //2.根据查询出的数据来删除订单明细

        orderDetailMapper.batchDelete(id);

        //3.删除订单
        orderMapper.delete(id);
    }


    /**
     * 再来一单
     *
     * @param id
     */
    @Override
    public void repetition(Long id) {
        //1.根据订单id查询数据
        Long userId = BaseContext.getCurrentId();
        List<OrderDetail> orderDetailList = orderDetailMapper.getByOrderId(id);
        if (CollUtil.isEmpty(orderDetailList)){
            log.error("没有订单id对应的订单详情数据");
        }
        //将获取的订单详情对象转换为购物车对象
        List<ShoppingCart> shoppingCartList = orderDetailList.stream().map(x -> {
            ShoppingCart shoppingCart = new ShoppingCart();

            //拷贝
            BeanUtils.copyProperties(x, shoppingCart, "id");
            shoppingCart.setUserId(userId);
            shoppingCart.setCreateTime(LocalDateTime.now());

            return shoppingCart;
        }).collect(Collectors.toList());

        //购物车数据批量添加到数据库
        shoppingCartMapper.batchInsert(shoppingCartList);
    }
}
